diff --git a/pmd-netbeans/build.xml b/pmd-netbeans/build.xml index b062070784..c486d01caa 100644 --- a/pmd-netbeans/build.xml +++ b/pmd-netbeans/build.xml @@ -7,6 +7,7 @@ + @@ -31,6 +32,7 @@ + @@ -52,6 +54,7 @@ + diff --git a/pmd-netbeans/lib/jakarta-oro-2.0.jar b/pmd-netbeans/lib/jakarta-oro-2.0.jar new file mode 100644 index 0000000000..3176673b7f Binary files /dev/null and b/pmd-netbeans/lib/jakarta-oro-2.0.jar differ diff --git a/pmd-netbeans/lib/oro-license b/pmd-netbeans/lib/oro-license new file mode 100644 index 0000000000..e61dd247ae --- /dev/null +++ b/pmd-netbeans/lib/oro-license @@ -0,0 +1,56 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2000 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation", "Jakarta-Oro" + * must not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * or "Jakarta-Oro", nor may "Apache" or "Jakarta-Oro" appear in their + * name, without prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + * Portions of this software are based upon software originally written + * by Daniel F. Savarese. We appreciate his contributions. + */ diff --git a/pmd-netbeans/src/manifest.mf b/pmd-netbeans/src/manifest.mf index 19f8226004..701914e87e 100644 --- a/pmd-netbeans/src/manifest.mf +++ b/pmd-netbeans/src/manifest.mf @@ -1,7 +1,7 @@ Manifest-Version: 1.0 OpenIDE-Module-Specification-Version: 0.71 Created-By: Ole-Martin Mørk -Class-Path: ext/pmd-1.04.jar ext/jaxen-core-1.0-fcs.jar ext/saxpath-1.0-fcs.jar +Class-Path: ext/pmd-1.04.jar ext/jaxen-core-1.0-fcs.jar ext/saxpath-1.0-fcs.jar ext/jakarta-oro-2.0.jar OpenIDE-Module: pmd OpenIDE-Module-Layer: pmd/mf-layer.xml OpenIDE-Module-IDE-Dependencies: IDE/1 > 2.23 diff --git a/pmd-netbeans/src/pmd/Bundle.properties b/pmd-netbeans/src/pmd/Bundle.properties index af1efbf63b..392f1f3566 100644 --- a/pmd-netbeans/src/pmd/Bundle.properties +++ b/pmd-netbeans/src/pmd/Bundle.properties @@ -35,3 +35,5 @@ OpenIDE-Module-Long-Description=Runs the PMD source code scanner tool. \ Hyperlinked Output Window display. LBL_pmd_annotation=PMD Error + +LBL_pmd_scan_annotation=PMD Realtime Scan Error diff --git a/pmd-netbeans/src/pmd/RunPMDAction.java b/pmd-netbeans/src/pmd/RunPMDAction.java index cd7dd2f895..6131a215c4 100644 --- a/pmd-netbeans/src/pmd/RunPMDAction.java +++ b/pmd-netbeans/src/pmd/RunPMDAction.java @@ -277,11 +277,11 @@ public class RunPMDAction extends CookieAction { private List getDataObjects( Node[] node ) { ArrayList list = new ArrayList(); for( int i = 0; i < node.length; i++ ) { - SourceCookie cookie = ( SourceCookie )node[i].getCookie( SourceCookie.class ); - + DataObject data = (DataObject)node[i].getCookie( DataObject.class ); + //Checks to see if it's a java source file - if( cookie != null ) { - list.add( ( DataObject )node[i].getCookie( DataObject.class ) ); + if( data.getPrimaryFile().hasExt( "java" ) ) { + list.add( data ); } //Or if it's a folder else { @@ -289,8 +289,7 @@ public class RunPMDAction extends CookieAction { Enumeration enumeration = folder.children( true ); while( enumeration.hasMoreElements() ) { DataObject dataobject = ( DataObject )enumeration.nextElement(); - cookie = ( SourceCookie )dataobject.getCookie( SourceCookie.class ); - if( cookie != null ) { + if( dataobject.getPrimaryFile().hasExt( "java" ) ) { list.add( dataobject ); } } diff --git a/pmd-netbeans/src/pmd/config/Bundle.properties b/pmd-netbeans/src/pmd/config/Bundle.properties index ec478edc2b..ed9d5147c8 100644 --- a/pmd-netbeans/src/pmd/config/Bundle.properties +++ b/pmd-netbeans/src/pmd/config/Bundle.properties @@ -37,3 +37,11 @@ PROP_classpath=Classpath PROP_rulesets=Rulesets HINT_rulesets=The custom rulesets to use + +PROP_enablescan=Enable scan + +HINT_enablescan=Enable realtime pmd scanning? + +PROP_scanInterval=Scan interval + +HINT_scanInterval=The number of seconds between each scan diff --git a/pmd-netbeans/src/pmd/config/PMDOptionsSettings.java b/pmd-netbeans/src/pmd/config/PMDOptionsSettings.java index 25930c65ea..d98b375de2 100644 --- a/pmd-netbeans/src/pmd/config/PMDOptionsSettings.java +++ b/pmd-netbeans/src/pmd/config/PMDOptionsSettings.java @@ -46,6 +46,10 @@ public class PMDOptionsSettings extends SystemOption { public final static String PROP_RULESETS = "rulesetz"; + public final static String PROP_SCAN_INTERVAL = "interval"; + + public final static String PROP_ENABLE_SCAN = "EnableScan"; + /** The default rules.*/ private static final String DEFAULT_RULES = "AvoidDuplicateLiterals, StringToString, StringInstantiation, JUnitStaticSuite, " + @@ -59,6 +63,7 @@ public class PMDOptionsSettings extends SystemOption { "AvoidReassigningParametersRule, OnlyOneReturn, UseSingletonRule, " + "DontImportJavaLang, UnusedImports, DuplicateImports, "; + // No constructor please! /** Sets the default rulesets and initializes the option */ @@ -134,4 +139,36 @@ public class PMDOptionsSettings extends SystemOption { putProperty( PROP_RULESETS, rulesets, true ); } + /** Getter for property scanEnabled. + * @return Value of property scanEnabled. + * + */ + public Boolean isScanEnabled() { + return (Boolean)getProperty( PROP_ENABLE_SCAN ); + } + + /** Setter for property scanEnabled. + * @param scanEnabled New value of property scanEnabled. + * + */ + public void setScanEnabled(Boolean scanEnabled) { + putProperty( PROP_ENABLE_SCAN, scanEnabled ); + } + + /** Getter for property scanInterval. + * @return Value of property scanInterval. + * + */ + public Integer getScanInterval() { + return (Integer)getProperty( PROP_SCAN_INTERVAL); + } + + /** Setter for property scanInterval. + * @param scanInterval New value of property scanInterval. + * + */ + public void setScanInterval(Integer scanInterval) { + putProperty( PROP_SCAN_INTERVAL, scanInterval ); + } + } diff --git a/pmd-netbeans/src/pmd/config/PMDOptionsSettingsBeanInfo.java b/pmd-netbeans/src/pmd/config/PMDOptionsSettingsBeanInfo.java index c9fc1fa06f..e7a263b4b7 100644 --- a/pmd-netbeans/src/pmd/config/PMDOptionsSettingsBeanInfo.java +++ b/pmd-netbeans/src/pmd/config/PMDOptionsSettingsBeanInfo.java @@ -27,6 +27,7 @@ package pmd.config; import java.awt.Image; +import java.awt.*; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.PropertyDescriptor; @@ -52,8 +53,9 @@ public class PMDOptionsSettingsBeanInfo extends SimpleBeanInfo { * @return the description of the rulesets property */ public PropertyDescriptor[] getPropertyDescriptors() { - PropertyDescriptor descriptor[] = new PropertyDescriptor[2]; + PropertyDescriptor descriptor[] = new PropertyDescriptor[4]; try { + PropertyDescriptor rules = new PropertyDescriptor( "rules", PMDOptionsSettings.class, "getRules", "setRules" ); rules.setDisplayName( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "PROP_rules" ) ); rules.setShortDescription( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "HINT_rules" ) ); @@ -66,6 +68,17 @@ public class PMDOptionsSettingsBeanInfo extends SimpleBeanInfo { rulesets.setPropertyEditorClass( RuleSetChooserEditor.class ); rulesets.setExpert(true); descriptor[1] = rulesets; + + PropertyDescriptor enableScan = new PropertyDescriptor( "scanEnabled", PMDOptionsSettings.class, "isScanEnabled", "setScanEnabled" ); + enableScan.setDisplayName( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "PROP_enablescan" ) ); + enableScan.setShortDescription( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "HINT_enablescan" ) ); + descriptor[2] = enableScan; + + PropertyDescriptor scanInterval = new PropertyDescriptor( "scanInterval", PMDOptionsSettings.class, "getScanInterval", "setScanInterval" ); + scanInterval.setDisplayName( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "PROP_scanInterval" ) ); + scanInterval.setShortDescription( NbBundle.getMessage( PMDOptionsSettingsBeanInfo.class, "HINT_scanInterval" ) ); + descriptor[3] = scanInterval; + } catch( IntrospectionException ie ) { ErrorManager.getDefault().notify( ie ); diff --git a/pmd-netbeans/src/pmd/config/ui/RuleEnabler.java b/pmd-netbeans/src/pmd/config/ui/RuleEnabler.java index be35241ae0..680d4bee4c 100644 --- a/pmd-netbeans/src/pmd/config/ui/RuleEnabler.java +++ b/pmd-netbeans/src/pmd/config/ui/RuleEnabler.java @@ -30,6 +30,7 @@ import java.beans.PropertyEditorSupport; import javax.swing.JPanel; import net.sourceforge.pmd.Rule; import java.awt.event.MouseEvent; +import org.apache.oro.text.perl.Perl5Util; /** The JPanel used to edit the Rule property * @author ole martin mørk @@ -37,6 +38,8 @@ import java.awt.event.MouseEvent; public class RuleEnabler extends JPanel { private final PropertyEditorSupport editor; + + private final static Perl5Util regex = new Perl5Util(); /** Creates a new editor * @param editor The object to be notified of changes in the property */ @@ -392,8 +395,8 @@ public class RuleEnabler extends JPanel { private void chosenListValueChanged() {//GEN-FIRST:event_chosenListValueChanged Rule rule = (Rule)chosenList.getSelectedValue(); if( rule != null ) { - example.setText( rule.getExample().trim()); - information.setText( rule.getDescription().trim() ); + example.setText( regex.substitute( "s/ +/ /g", rule.getExample().trim() ) ); + information.setText( regex.substitute( "s/ +/ /g", rule.getDescription().trim() ) ); properties.setModel( new PropertiesModel( rule ) ); } }//GEN-LAST:event_chosenListValueChanged @@ -404,8 +407,8 @@ public class RuleEnabler extends JPanel { private void availableListValueChanged() {//GEN-FIRST:event_availableListValueChanged Rule rule = (Rule)availableList.getSelectedValue(); if( rule != null ) { - example.setText( rule.getExample().trim() ); - information.setText( rule.getDescription().trim() ); + example.setText( regex.substitute( "s/ +/ /g", rule.getExample().trim() ) ); + information.setText( regex.substitute( "s/ +/ /g", rule.getDescription().trim() ) ); properties.setModel( new PropertiesModel( rule ) ); } }//GEN-LAST:event_availableListValueChanged diff --git a/pmd-netbeans/src/pmd/mf-layer.xml b/pmd-netbeans/src/pmd/mf-layer.xml index e1f4f21493..26c47a97a2 100644 --- a/pmd-netbeans/src/pmd/mf-layer.xml +++ b/pmd-netbeans/src/pmd/mf-layer.xml @@ -26,6 +26,7 @@ + diff --git a/pmd-netbeans/src/pmd/resources/annotation-scan.xml b/pmd-netbeans/src/pmd/resources/annotation-scan.xml new file mode 100644 index 0000000000..fd9e30fcb2 --- /dev/null +++ b/pmd-netbeans/src/pmd/resources/annotation-scan.xml @@ -0,0 +1,13 @@ + + + + diff --git a/pmd-netbeans/src/pmd/scan/EditorChangeListener.java b/pmd-netbeans/src/pmd/scan/EditorChangeListener.java index 0979b881ca..e3e857ad55 100644 --- a/pmd-netbeans/src/pmd/scan/EditorChangeListener.java +++ b/pmd-netbeans/src/pmd/scan/EditorChangeListener.java @@ -26,11 +26,13 @@ */ package pmd.scan; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.openide.ErrorManager; -import org.openide.cookies.SourceCookie; +import org.openide.cookies.EditorCookie; import org.openide.nodes.Node; import org.openide.windows.TopComponent.Registry; +import pmd.config.PMDOptionsSettings; /** * @@ -45,20 +47,22 @@ public class EditorChangeListener implements PropertyChangeListener { } - public void propertyChange(java.beans.PropertyChangeEvent propertyChangeEvent) { - Node node[] = registry.getActivatedNodes(); - SourceCookie cookie = null; - int i = 0; - for( i = 0; i < node.length; i++ ) { - ErrorManager.getDefault().log(ErrorManager.ERROR, "checking cookie " + node[i]); - cookie = (SourceCookie)node[i].getCookie( SourceCookie.class ); - if( cookie != null ) { - break; + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + if( PMDOptionsSettings.getDefault().isScanEnabled().equals( Boolean.TRUE ) ) { + Node node[] = registry.getActivatedNodes(); + EditorCookie cookie = null; + int i = 0; + for( i = 0; i < node.length; i++ ) { + ErrorManager.getDefault().log(ErrorManager.ERROR, "checking cookie " + node[i]); + cookie = (EditorCookie)node[i].getCookie( EditorCookie.class ); + if( cookie != null ) { + break; + } + } + if( cookie != null ) { + ErrorManager.getDefault().log(ErrorManager.ERROR, "starting scan"); + startScan( node[i] ); } - } - if( cookie != null ) { - ErrorManager.getDefault().log(ErrorManager.ERROR, "starting scan"); - startScan( node[i] ); } } @@ -71,7 +75,6 @@ public class EditorChangeListener implements PropertyChangeListener { Thread thread = new Thread( scanner ); thread.setPriority( Thread.MIN_PRIORITY ); thread.start(); - int i; } } diff --git a/pmd-netbeans/src/pmd/scan/PMDScanAnnotation.java b/pmd-netbeans/src/pmd/scan/PMDScanAnnotation.java new file mode 100644 index 0000000000..d886c42e1a --- /dev/null +++ b/pmd-netbeans/src/pmd/scan/PMDScanAnnotation.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2002-2003, Ole-Martin Mørk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ +package pmd.scan; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.openide.text.Annotation; +import org.openide.text.Line; + +/** + * Just a class thats mission is to mark the line where the error is. It's using + * pmd-annotation type to mark the line + * + * @author ole martin mørk + * @created 3. november 2002 + */ +public class PMDScanAnnotation extends Annotation implements PropertyChangeListener { + + /** The error message shown on mouseover on the pmd icon */ + private String errormessage = null; + private static List annotations = new ArrayList(); + + private PMDScanAnnotation() {} + + public static final PMDScanAnnotation getNewInstance() { + PMDScanAnnotation pmd = new PMDScanAnnotation(); + annotations.add( pmd ); + return pmd; + } + + public static final void clearAll() { + Iterator iterator = annotations.iterator(); + while( iterator.hasNext() ) { + ((Annotation)iterator.next()).detach(); + } + annotations.clear(); + } + + /** + * The annotation type. + * + * @return pmd-annotation + */ + public String getAnnotationType() { + return "pmd-scan-annotation"; + } + + + /** + * Sets the current errormessage + * + * @param message the errormessage + */ + public void setErrorMessage( String message ) { + errormessage = message; + } + + + /** + * A short description of this annotation + * + * @return the short description + */ + public String getShortDescription() { + return errormessage; + } + + + /** + * Invoked when the user change the content on the line where the annotation is + * attached + * + * @param propertyChangeEvent the event fired + */ + public void propertyChange( PropertyChangeEvent propertyChangeEvent ) { + Line line = ( Line )propertyChangeEvent.getSource(); + line.removePropertyChangeListener( this ); + detach(); + } +} diff --git a/pmd-netbeans/src/pmd/scan/Scanner.java b/pmd-netbeans/src/pmd/scan/Scanner.java index 064af0d390..a32708efd0 100644 --- a/pmd-netbeans/src/pmd/scan/Scanner.java +++ b/pmd-netbeans/src/pmd/scan/Scanner.java @@ -38,6 +38,8 @@ import org.openide.text.Line.Set; import pmd.Fault; import pmd.PMDAnnotation; import pmd.RunPMDAction; +import pmd.config.PMDOptionsSettings; +import pmd.scan.PMDScanAnnotation; /** * @@ -60,11 +62,8 @@ public class Scanner implements Runnable { list.add( object ); List faults = RunPMDAction.checkCookies(list ); ErrorManager.getDefault().log(ErrorManager.ERROR, ""+faults); - - + PMDScanAnnotation.clearAll(); LineCookie cookie = ( LineCookie )object.getCookie( LineCookie.class ); - - Set lineset = cookie.getLineSet(); for( int i = 0; i < faults.size(); i++ ) { Fault fault = (Fault)faults.get( i ); @@ -72,7 +71,7 @@ public class Scanner implements Runnable { Line line = lineset.getOriginal( lineNum - 1 ); ErrorManager.getDefault().log( ErrorManager.ERROR, "count: " + line.getAnnotationCount() ); if( line.getAnnotationCount() <= 0 ) { - PMDAnnotation annotation = PMDAnnotation.getNewInstance(); + PMDScanAnnotation annotation = PMDScanAnnotation.getNewInstance(); String msg = fault.getMessage(); annotation.setErrorMessage( msg ); annotation.attach( line ); @@ -80,7 +79,7 @@ public class Scanner implements Runnable { line.addPropertyChangeListener( annotation ); } } - Thread.sleep( 3000 ); + Thread.sleep( PMDOptionsSettings.getDefault().getScanInterval().intValue() * 1000 ); } } catch( IOException e ) {