From a7a9fc55c9e080f679a97b6693c01091602777ce Mon Sep 17 00:00:00 2001 From: Radim Kubacki Date: Thu, 16 Mar 2006 09:13:28 +0000 Subject: [PATCH] removing module install class and larger rewrite of automatic scanning (mostly to address http://www.netbeans.org/issues/show_bug.cgi?id=72766) git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@4300 51baf565-9d33-0410-a72c-fc3788e3496d --- pmd-netbeans/manifest.mf | 1 - pmd-netbeans/src/pmd/NbRuleSetFactory.java | 26 +++ pmd-netbeans/src/pmd/PMDInstall.java | 20 -- pmd-netbeans/src/pmd/RunPMDAction.java | 6 +- pmd-netbeans/src/pmd/config/ConfigUtils.java | 57 ++--- .../src/pmd/scan/EditorChangeListener.java | 7 +- pmd-netbeans/src/pmd/scan/Scanner.java | 204 ++++++++---------- .../test/unit/src/pmd/RunPMDActionTest.java | 6 +- 8 files changed, 155 insertions(+), 172 deletions(-) delete mode 100644 pmd-netbeans/src/pmd/PMDInstall.java diff --git a/pmd-netbeans/manifest.mf b/pmd-netbeans/manifest.mf index 6584853ea8..4c9121fe47 100644 --- a/pmd-netbeans/manifest.mf +++ b/pmd-netbeans/manifest.mf @@ -2,7 +2,6 @@ Manifest-Version: 1.0 OpenIDE-Module-Specification-Version: 1.5.1 Created-By: Ole-Martin Mørk and Gunnlaugur Þór Briem and Radim Kubacki OpenIDE-Module: pmd -OpenIDE-Module-Install: pmd/PMDInstall.class OpenIDE-Module-Layer: pmd/mf-layer.xml OpenIDE-Module-Localizing-Bundle: pmd/Bundle.properties OpenIDE-Module-Requires: diff --git a/pmd-netbeans/src/pmd/NbRuleSetFactory.java b/pmd-netbeans/src/pmd/NbRuleSetFactory.java index 34483d637f..2d57ff81d0 100644 --- a/pmd-netbeans/src/pmd/NbRuleSetFactory.java +++ b/pmd-netbeans/src/pmd/NbRuleSetFactory.java @@ -1,3 +1,29 @@ +/* + * Copyright (c) 2002-2003, the pmd-netbeans team + * 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; import org.w3c.dom.Document; diff --git a/pmd-netbeans/src/pmd/PMDInstall.java b/pmd-netbeans/src/pmd/PMDInstall.java deleted file mode 100644 index 972c029dfc..0000000000 --- a/pmd-netbeans/src/pmd/PMDInstall.java +++ /dev/null @@ -1,20 +0,0 @@ -package pmd; - -import org.openide.modules.ModuleInstall; - -/** Extends default set of rules avaliable in PMD. - * - * @author Radim Kubacki - */ -public class PMDInstall extends ModuleInstall { - - /** Adds custom RuleSetFactory when IDE is started. */ - public void restored () { - pmd.config.ConfigUtils.addRuleSetFactory (NbRuleSetFactory.getDefault ()); - } - - /** Unregisters RuleSetFactory. */ - public void uninstalled () { - pmd.config.ConfigUtils.removeRuleSetFactory (NbRuleSetFactory.getDefault ()); - } -} diff --git a/pmd-netbeans/src/pmd/RunPMDAction.java b/pmd-netbeans/src/pmd/RunPMDAction.java index 48c5f0ad4a..6a8f317ae5 100644 --- a/pmd-netbeans/src/pmd/RunPMDAction.java +++ b/pmd-netbeans/src/pmd/RunPMDAction.java @@ -158,7 +158,7 @@ public class RunPMDAction extends CookieAction { * @return the list of rule violations found in the run, not null. Elements are instanceof {@link Fault}. * @throws IOException on failure to read one of the files or to write to the output window. */ - public static List checkCookies( List/**/ dataobjects ) throws IOException { + public static List/**/ performScan( List/**/ dataobjects ) throws IOException { assert dataobjects != null: "Cannot pass null to RunPMDAction.checkCookies()"; SourceLevelQuery sourceLevelQuery = (SourceLevelQuery) Lookup.getDefault().lookup(SourceLevelQuery.class); @@ -166,7 +166,7 @@ public class RunPMDAction extends CookieAction { PMD pmd_1_3 = null; PMD pmd_1_4 = null; PMD pmd_1_5 = null; - ArrayList list = new ArrayList( 100 ); + ArrayList/**/ list = new ArrayList( 100 ); CancelCallback cancel = new CancelCallback(); ProgressHandle prgHdl = ProgressHandleFactory.createHandle("PMD check", cancel); // PENDING action to show output @@ -274,7 +274,7 @@ public class RunPMDAction extends CookieAction { try { StatusDisplayer.getDefault().setStatusText("PMD checking for rule violations"); List list = getDataObjects(node); - List violations = checkCookies(list); + List violations = performScan(list); IOProvider ioProvider = (IOProvider)Lookup.getDefault().lookup(IOProvider.class); InputOutput output = ioProvider.getIO("PMD output", false); if(violations.isEmpty()) { diff --git a/pmd-netbeans/src/pmd/config/ConfigUtils.java b/pmd-netbeans/src/pmd/config/ConfigUtils.java index bfd4577b1e..0a30615ee6 100644 --- a/pmd-netbeans/src/pmd/config/ConfigUtils.java +++ b/pmd-netbeans/src/pmd/config/ConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003, the pmd-netbeans team + * Copyright (c) 2002-2006, the pmd-netbeans team * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -38,6 +38,7 @@ import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSetNotFoundException; import org.openide.ErrorManager; +import pmd.NbRuleSetFactory; import pmd.config.ui.RuleComparator; import pmd.custom.RuleClassLoader; @@ -46,34 +47,34 @@ import pmd.custom.RuleClassLoader; */ public abstract class ConfigUtils { - /** - * Extra ruleset factories added by calling {@link #addRuleSetFactory}. - * May be null (equivalent to empty). - */ - private static ArrayList extraFactories = null; + /** + * Extra ruleset factories added by calling {@link #addRuleSetFactory}. + * May be null (equivalent to empty). + */ + private static ArrayList extraFactories; - /** - * Registers extra rules that are available. - * - * @param rules Collection of Rule objects. - */ - public static synchronized void addRuleSetFactory(RuleSetFactory fact) { - if (extraFactories == null) { - extraFactories = new ArrayList(); - } - extraFactories.add(fact); - } - - /** - * Unregisters extra rules previously registered. - * - * @param rules Collection of Rule objects. - */ - public static synchronized void removeRuleSetFactory(RuleSetFactory fact) { - if (extraFactories != null) { - extraFactories.remove(fact); - } - } + static { + extraFactories = new ArrayList(); + extraFactories.add(NbRuleSetFactory.getDefault ()); + } + + /** + * Registers extra rules that are available. + * + * @param rules Collection of Rule objects. + */ + public static synchronized void addRuleSetFactory(RuleSetFactory fact) { + extraFactories.add(fact); + } + + /** + * Unregisters extra rules previously registered. + * + * @param rules Collection of Rule objects. + */ + public static synchronized void removeRuleSetFactory(RuleSetFactory fact) { + extraFactories.remove(fact); + } /** * Determines the list of rules to use. This is done by iterating over all diff --git a/pmd-netbeans/src/pmd/scan/EditorChangeListener.java b/pmd-netbeans/src/pmd/scan/EditorChangeListener.java index f4dc9dfc72..1cd39410cd 100644 --- a/pmd-netbeans/src/pmd/scan/EditorChangeListener.java +++ b/pmd-netbeans/src/pmd/scan/EditorChangeListener.java @@ -62,7 +62,7 @@ public class EditorChangeListener implements PropertyChangeListener { // settings changed, so chuck out current scanner if any. if(scanner != null) { tracelog("Stopping scanner " + scanner + " because of changed PMD settings"); - scanner.stopThread(); + scanner.cancel(); scanner = null; currentlyScannedNode = null; } @@ -99,14 +99,11 @@ public class EditorChangeListener implements PropertyChangeListener { } // not the same one, so we replace the scanner. tracelog(" Stopping scanner " + scanner); - scanner.stopThread(); + scanner.cancel(); } scanner = new Scanner( node ); tracelog(" Starting scanner " + scanner); - Thread thread = new Thread( scanner ); - thread.setPriority( Thread.MIN_PRIORITY ); this.currentlyScannedNode = node; - thread.start(); } private void tracelog(String str) { diff --git a/pmd-netbeans/src/pmd/scan/Scanner.java b/pmd-netbeans/src/pmd/scan/Scanner.java index 317de8e05d..f0454c89ab 100644 --- a/pmd-netbeans/src/pmd/scan/Scanner.java +++ b/pmd-netbeans/src/pmd/scan/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2003, the pmd-netbeans team + * Copyright (c) 2002-2006, the pmd-netbeans team * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -44,6 +44,7 @@ import org.openide.cookies.LineCookie; import org.openide.nodes.Node; import org.openide.text.Line; import org.openide.text.Line.Part; +import org.openide.util.RequestProcessor; import pmd.Fault; import pmd.RunPMDAction; import pmd.config.PMDOptionsSettings; @@ -53,114 +54,93 @@ import pmd.config.PMDOptionsSettings; */ public class Scanner implements Runnable, DocumentListener, PropertyChangeListener { - private final Node node; - private boolean running = true; - private StyledDocument subscribedDoc = null; - private EditorCookie.Observable subscribedObservable = null; - - /** - * If this is -1, scan constantly. Else, scan only when this has changed. - */ - private int modCount; - - /** Creates a new instance of Scanner */ - public Scanner( Node node ) { - this.node = node; - EditorCookie edtCookie = (EditorCookie)node.getCookie(EditorCookie.class); - if(edtCookie != null) { - StyledDocument doc = edtCookie.getDocument(); - if(doc != null) { - doc.removeDocumentListener(this); // prevent duplicate listener registration - doc.addDocumentListener(this); - subscribedDoc = doc; - } // else document has probably been unloaded because the editor window was closed. - EditorCookie.Observable obs = (EditorCookie.Observable)node.getCookie(EditorCookie.Observable.class); - if(obs != null) { - obs.removePropertyChangeListener(this); // prevent duplicate listener registration - obs.addPropertyChangeListener(this); - subscribedObservable = obs; - } - modCount = 0; - } else { - modCount = -1; - } - - } + private static RequestProcessor PMD_RP = new RequestProcessor("PMD scanner", 1); + + private final Node node; + private boolean running = true; + private StyledDocument subscribedDoc = null; + private EditorCookie.Observable subscribedObservable = null; + + private RequestProcessor.Task task; + + /** Creates a new instance of Scanner. + * This is created from EditorChangeListener only. + */ + Scanner( Node node ) { + this.node = node; + EditorCookie edtCookie = (EditorCookie)node.getCookie(EditorCookie.class); + if(edtCookie != null) { + StyledDocument doc = edtCookie.getDocument(); + if(doc != null) { + doc.removeDocumentListener(this); // prevent duplicate listener registration + doc.addDocumentListener(this); + subscribedDoc = doc; + } // else document has probably been unloaded because the editor window was closed. + EditorCookie.Observable obs = (EditorCookie.Observable)node.getCookie(EditorCookie.Observable.class); + if(obs != null) { + obs.removePropertyChangeListener(this); // prevent duplicate listener registration + obs.addPropertyChangeListener(this); + subscribedObservable = obs; + } + } + + task = PMD_RP.post(this, PMDOptionsSettings.getDefault().getScanInterval().intValue() * 1000, Thread.MIN_PRIORITY); + } public StyledDocument getSubscribedDocument() { return subscribedDoc; } - public void run() { - try { - tracelog("started"); - while( running ) { - - int tabSize = 8; - Integer foo = (Integer) Settings.getValue(JavaKit.class, SettingsNames.TAB_SIZE); - if (foo != null) - tabSize = foo.intValue(); - - int lastModCount = modCount; - tracelog("run starting at modcount: " + lastModCount); - DataObject object = ( DataObject )node.getCookie( DataObject.class ) ; - LineCookie cookie = ( LineCookie )object.getCookie( LineCookie.class ); - Line.Set lineset = cookie.getLineSet(); - List list = Collections.singletonList(object); - List faults = RunPMDAction.checkCookies(list ); - PMDScanAnnotation.clearAll(); - for( int i = 0; i < faults.size(); i++ ) { - Fault fault = (Fault)faults.get( i ); - int lineNum = fault.getLine(); - Line line = lineset.getCurrent( lineNum - 1 ); - if(line == null) - { - tracelog("no original line found for line " + lineNum + " in lineset; probably document closed" ); - } - else - { - tracelog("Line class : " + line.getClass().getName()); - tracelog("Node: " + node + ", count: " + line.getAnnotationCount() ); - - String text = line.getText(); - if (text != null) { - int firstNonWhiteSpaceCharIndex = findFirstNonWhiteSpaceCharIndex(text); - if (firstNonWhiteSpaceCharIndex == -1) - continue; - int lastNonWhiteSpaceCharIndex = findLastNonWhiteSpaceCharIndex(text); - String initialWhiteSpace = text.substring(0, firstNonWhiteSpaceCharIndex); - String content = text.substring(firstNonWhiteSpaceCharIndex, lastNonWhiteSpaceCharIndex + 1); - int start = expandedLength(0, initialWhiteSpace, tabSize); - int length = expandedLength(start, content, tabSize); + public void run() { + try { + tracelog("started"); + + int tabSize = 8; + Integer foo = (Integer) Settings.getValue(JavaKit.class, SettingsNames.TAB_SIZE); + if (foo != null) + tabSize = foo.intValue(); - Part part = line.createPart(start, length); + DataObject object = ( DataObject )node.getCookie( DataObject.class ) ; + LineCookie cookie = ( LineCookie )object.getCookie( LineCookie.class ); + Line.Set lineset = cookie.getLineSet(); + List list = Collections.singletonList(object); + List faults = RunPMDAction.performScan(list ); + PMDScanAnnotation.clearAll(); + for( int i = 0; i < faults.size(); i++ ) { + Fault fault = (Fault)faults.get( i ); + int lineNum = fault.getLine(); + Line line = lineset.getCurrent( lineNum - 1 ); + if(line == null) { + tracelog("no original line found for line " + lineNum + " in lineset; probably document closed" ); + } else { + tracelog("Line class : " + line.getClass().getName()); + tracelog("Node: " + node + ", count: " + line.getAnnotationCount() ); - PMDScanAnnotation annotation = PMDScanAnnotation.getNewInstance(); - String msg = fault.getMessage(); - annotation.setErrorMessage( msg ); - annotation.attach( part ); - part.addPropertyChangeListener( annotation ); - } - } - } - tracelog("run finished at modcount: " + lastModCount); - do { - try { - Thread.sleep( PMDOptionsSettings.getDefault().getScanInterval().intValue() * 1000 ); - } - catch( InterruptedException e ) { - ErrorManager.getDefault().notify(e); - } - } while(running && modCount != -1 && modCount == lastModCount); - } - } - catch( IOException e ) { - ErrorManager.getDefault().notify(e); - } - finally { - tracelog("stopped"); - } - } + String text = line.getText(); + if (text != null) { + int firstNonWhiteSpaceCharIndex = findFirstNonWhiteSpaceCharIndex(text); + if (firstNonWhiteSpaceCharIndex == -1) + continue; + int lastNonWhiteSpaceCharIndex = findLastNonWhiteSpaceCharIndex(text); + String initialWhiteSpace = text.substring(0, firstNonWhiteSpaceCharIndex); + String content = text.substring(firstNonWhiteSpaceCharIndex, lastNonWhiteSpaceCharIndex + 1); + int start = expandedLength(0, initialWhiteSpace, tabSize); + int length = expandedLength(start, content, tabSize); + + Part part = line.createPart(start, length); + + PMDScanAnnotation annotation = PMDScanAnnotation.getNewInstance(); + String msg = fault.getMessage(); + annotation.setErrorMessage( msg ); + annotation.attach( part ); + part.addPropertyChangeListener( annotation ); + } + } + } + } catch( IOException e ) { + ErrorManager.getDefault().notify(e); + } + } private int findFirstNonWhiteSpaceCharIndex(String text) { for (int i = 0; i < text.length(); i++) { @@ -200,8 +180,9 @@ public class Scanner implements Runnable, DocumentListener, PropertyChangeListen return length; } - public void stopThread() { - running = false; + public void cancel() { + task.cancel(); + task = null; } public String toString() { @@ -213,11 +194,15 @@ public class Scanner implements Runnable, DocumentListener, PropertyChangeListen } public void insertUpdate(DocumentEvent evt) { - incrementModCount(); + if (task != null) { + task.schedule(PMDOptionsSettings.getDefault().getScanInterval().intValue() * 1000); + } } public void removeUpdate(DocumentEvent evt) { - incrementModCount(); + if (task != null) { + task.schedule(PMDOptionsSettings.getDefault().getScanInterval().intValue() * 1000); + } } public void propertyChange(PropertyChangeEvent evt) { @@ -230,8 +215,7 @@ public class Scanner implements Runnable, DocumentListener, PropertyChangeListen StyledDocument doc = cookie.getDocument(); if(doc == null) { // stop the scanner thread -- this document has ben closed. - running = false; - incrementModCount(); + cancel(); } else { doc.removeDocumentListener(this); doc.addDocumentListener(this); @@ -252,10 +236,6 @@ public class Scanner implements Runnable, DocumentListener, PropertyChangeListen } } - private synchronized void incrementModCount() { - modCount++; - } - private void tracelog(String str) { if(RunPMDAction.TRACE_LOGGING) { ErrorManager.getDefault().log(ErrorManager.ERROR, this.toString() + ": " + str); diff --git a/pmd-netbeans/test/unit/src/pmd/RunPMDActionTest.java b/pmd-netbeans/test/unit/src/pmd/RunPMDActionTest.java index c158615989..2f944262bd 100644 --- a/pmd-netbeans/test/unit/src/pmd/RunPMDActionTest.java +++ b/pmd-netbeans/test/unit/src/pmd/RunPMDActionTest.java @@ -77,7 +77,7 @@ public class RunPMDActionTest extends NbTestCase { // try on empty list - result = pmd.RunPMDAction.checkCookies(Collections.EMPTY_LIST); + result = pmd.RunPMDAction.performScan(Collections.EMPTY_LIST); // assertEquals(expResult, result); FileObject dir = FileUtil.toFileObject(getWorkDir()); @@ -87,7 +87,7 @@ public class RunPMDActionTest extends NbTestCase { assertNotNull("Cannot create file in work dir", f1); DataObject d1 = DataObject.find(f1); assertNotNull("Cannot find a data object", d1); - result = pmd.RunPMDAction.checkCookies(Collections.singletonList(d1)); + result = pmd.RunPMDAction.performScan(Collections.singletonList(d1)); assertEquals("There should be no error for MANIFEST.MF file", 0, result.size()); f1 = dir.createData("PMDSample.java"); @@ -106,7 +106,7 @@ public class RunPMDActionTest extends NbTestCase { } d1 = DataObject.find(f1); assertNotNull("Cannot find a data object", d1); - result = pmd.RunPMDAction.checkCookies(Collections.singletonList(d1)); + result = pmd.RunPMDAction.performScan(Collections.singletonList(d1)); assertEquals("There should be no error for PMDSample.java file", 0, result.size()); }