From 53197d9be9366ccf9ebccc1e6e31270c1dff8e95 Mon Sep 17 00:00:00 2001 From: Oliver Burn Date: Tue, 11 Mar 2003 06:56:45 +0000 Subject: [PATCH] Patch from David Schneider to add Severity to logged messages. --- .../tools/checkstyle/AuditEvent.java | 13 +- .../tools/checkstyle/DefaultLogger.java | 9 +- .../tools/checkstyle/XMLLogger.java | 3 + .../tools/checkstyle/api/Check.java | 40 +++- .../checkstyle/api/LocalizedMessage.java | 55 ++++++ .../tools/checkstyle/api/SeverityLevel.java | 184 ++++++++++++++++++ .../tools/checkstyle/XMLLoggerTest.java | 46 ++--- 7 files changed, 318 insertions(+), 32 deletions(-) create mode 100755 src/checkstyle/com/puppycrawl/tools/checkstyle/api/SeverityLevel.java diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java index 5b1233df7..3de2dea03 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/AuditEvent.java @@ -18,10 +18,11 @@ //////////////////////////////////////////////////////////////////////////////// package com.puppycrawl.tools.checkstyle; -import com.puppycrawl.tools.checkstyle.api.LocalizedMessage; - import java.util.EventObject; +import com.puppycrawl.tools.checkstyle.api.LocalizedMessage; +import com.puppycrawl.tools.checkstyle.api.SeverityLevel; + /** * Raw event for audit. *

@@ -112,6 +113,14 @@ public final class AuditEvent return mMessage.getColumnNo(); } + /** @return the audit event severity level **/ + public SeverityLevel getSeverityLevel() + { + return (mMessage == null) + ? SeverityLevel.WARNING + : mMessage.getSeverityLevel(); + } + /** @return the localized message **/ public LocalizedMessage getLocalizedMessage() { diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java index 1886b89aa..c0bb35f82 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/DefaultLogger.java @@ -83,13 +83,12 @@ public class DefaultLogger **/ public void addError(AuditEvent aEvt) { - String fileName = aEvt.getFileName(); - String message = aEvt.getMessage(); + final String fileName = aEvt.getFileName(); + final String message = aEvt.getMessage(); // avoid StringBuffer.expandCapacity - int bufLen = fileName.length() + message.length() + 12; - - StringBuffer sb = new StringBuffer(bufLen); + final int bufLen = fileName.length() + message.length() + 12; + final StringBuffer sb = new StringBuffer(bufLen); sb.append(fileName); sb.append(':').append(aEvt.getLine()); diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java index cbbe9bf9c..1e7bb9e2a 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/XMLLogger.java @@ -111,6 +111,9 @@ public class XMLLogger if (aEvt.getColumn() > 0) { mWriter.print(" column=\"" + aEvt.getColumn() + "\""); } + mWriter.print(" severity=\"" + + aEvt.getSeverityLevel().getName() + + "\""); mWriter.println(" message=\"" + encode(aEvt.getMessage()) + "\"/>"); } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java index 20450c87c..756232b52 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java @@ -21,6 +21,7 @@ package com.puppycrawl.tools.checkstyle.api; import java.util.HashSet; import java.util.Set; + /** * The base class for checks. * @@ -46,6 +47,9 @@ public abstract class Check extends AutomaticBean /** the tab with for column reporting */ private int mTabWidth = 8; // meaningful default + /** the severity level of any violations found */ + private SeverityLevel mSeverityLevel = SeverityLevel.WARNING; + /** current class loader */ private ClassLoader mLoader = Thread.currentThread().getContextClassLoader(); @@ -223,6 +227,38 @@ public abstract class Check extends AutomaticBean mTabWidth = aTabWidth; } + /** + * Returns the severity level of the check. + * @return the severity level + * @see com.puppycrawl.tools.checkstyle.SeverityLevel + */ + public final SeverityLevel getSeverityLevel() + { + return mSeverityLevel; + } + + /** + * Sets the severity level. The string should be one of the names + * defined in the SeverityLevel class. + * + * @param aSeverity The new severity level + * @see com.puppycrawl.tools.checkstyle.SeverityLevel + */ + public void setSeverity(String aSeverity) + { + mSeverityLevel = SeverityLevel.getInstance(aSeverity); + } + + /** + * Get the severity level's name. + * + * @return the check's severity level name. + */ + public String getSeverity() + { + return mSeverityLevel.getName(); + } + /** * Log an error message. * @@ -246,7 +282,7 @@ public abstract class Check extends AutomaticBean protected final void log(int aLine, String aKey, Object aArgs[]) { mMessages.add(new LocalizedMessage( - aLine, getResourceBundle(), aKey, aArgs)); + aLine, getResourceBundle(), aKey, aArgs, mSeverityLevel)); } @@ -347,7 +383,7 @@ public abstract class Check extends AutomaticBean final int col = 1 + Utils.lengthExpandedTabs( getLines()[aLineNo - 1], aColNo, getTabWidth()); mMessages.add(new LocalizedMessage( - aLineNo, col, getResourceBundle(), aKey, aArgs)); + aLineNo, col, getResourceBundle(), aKey, aArgs, mSeverityLevel)); } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java index e6adad0b9..f5eb2a495 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/LocalizedMessage.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; + /** * Represents a message that can be localised. The translations come from * message.properties files. The underlying implementation uses @@ -52,6 +53,11 @@ public final class LocalizedMessage /** the column number **/ private final int mColNo; + /** the severity level **/ + private final SeverityLevel mSeverityLevel; + /** the default severity level if one is not specified */ + private static final SeverityLevel DEFAULT_SEVERITY = SeverityLevel.WARNING; + /** key for the message format **/ private final String mKey; @@ -123,6 +129,32 @@ public final class LocalizedMessage mKey = aKey; mArgs = aArgs; mBundle = aBundle; + mSeverityLevel = DEFAULT_SEVERITY; + } + + /** + * Creates a new LocalizedMessage instance. + * + * @param aLineNo line number associated with the message + * @param aColNo column number associated with the message + * @param aBundle resource bundle name + * @param aKey the key to locate the translation + * @param aArgs arguments for the translation + * @param aSeverityLevel severity level for the message + */ + public LocalizedMessage(int aLineNo, + int aColNo, + String aBundle, + String aKey, + Object[] aArgs, + SeverityLevel aSeverityLevel) + { + mLineNo = aLineNo; + mColNo = aColNo; + mKey = aKey; + mArgs = aArgs; + mBundle = aBundle; + mSeverityLevel = aSeverityLevel; } /** @@ -140,6 +172,23 @@ public final class LocalizedMessage this(aLineNo, 0, aBundle, aKey, aArgs); } + /** + * Creates a new LocalizedMessage instance. The column number + * defaults to 0. + * + * @param aLineNo line number associated with the message + * @param aBundle name of a resource bundle that contains error messages + * @param aKey the key to locate the translation + * @param aArgs arguments for the translation + * @param aSeverityLevel severity level for the message + */ + public LocalizedMessage( + int aLineNo, String aBundle, String aKey, Object[] aArgs, + SeverityLevel aSeverityLevel) + { + this(aLineNo, 0, aBundle, aKey, aArgs, aSeverityLevel); + } + /** @return the translated message **/ public String getMessage() { @@ -187,6 +236,12 @@ public final class LocalizedMessage return mColNo; } + /** @return the severity level **/ + public SeverityLevel getSeverityLevel() + { + return mSeverityLevel; + } + /** * Returns the message key to locate the translation, can also be used * in IDE plugins to map error messages to corrective actions. diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/SeverityLevel.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/SeverityLevel.java new file mode 100755 index 000000000..540159c08 --- /dev/null +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/SeverityLevel.java @@ -0,0 +1,184 @@ +//////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code for adherence to a set of rules. +// Copyright (C) 2001-2002 Oliver Burn +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//////////////////////////////////////////////////////////////////////////////// +package com.puppycrawl.tools.checkstyle.api; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +/** + * Severity level for a check violation. + *

+ * Each violation of an audit check is assigned one of the severity levels + * defined here. + * + * @author David Schneider + */ +public final class SeverityLevel implements Comparable, Serializable +{ + /** Numeric value for severity level IGNORE */ + private static final int SEVERITYCODE_IGNORE = 10; + /** Numeric value for severity level INFO */ + private static final int SEVERITYCODE_INFO = 20; + /** Numeric value for severity level WARNING */ + private static final int SEVERITYCODE_WARNING = 30; + /** Numeric value for severity level ERROR */ + private static final int SEVERITYCODE_ERROR = 40; + + + /** Name for severity level IGNORE */ + private static final String SEVERITYNAME_IGNORE = "ignore"; + /** Name for severity level INFO */ + private static final String SEVERITYNAME_INFO = "info"; + /** Name for severity level WARNING */ + private static final String SEVERITYNAME_WARNING = "warning"; + /** Name for severity level ERROR */ + private static final String SEVERITYNAME_ERROR = "error"; + + /** nothing scope */ + public static final SeverityLevel IGNORE = + new SeverityLevel(SEVERITYCODE_IGNORE, SEVERITYNAME_IGNORE); + + /** public scope */ + public static final SeverityLevel INFO = + new SeverityLevel(SEVERITYCODE_INFO, SEVERITYNAME_INFO); + + /** protected scope */ + public static final SeverityLevel WARNING = + new SeverityLevel(SEVERITYCODE_WARNING, SEVERITYNAME_WARNING); + + /** package scope */ + public static final SeverityLevel ERROR = + new SeverityLevel(SEVERITYCODE_ERROR, SEVERITYNAME_ERROR); + + /** map from scope names to the respective Scope */ + private static final Map NAME_TO_SCOPE = new HashMap(); + static { + NAME_TO_SCOPE.put(SEVERITYNAME_IGNORE, IGNORE); + NAME_TO_SCOPE.put(SEVERITYNAME_INFO, INFO); + NAME_TO_SCOPE.put(SEVERITYNAME_WARNING, WARNING); + NAME_TO_SCOPE.put(SEVERITYNAME_ERROR, ERROR); + } + + /** the SEVERITYCODE_XYZ value of this severity level. */ + private final int mCode; + + /** the name of this severity level. */ + private final String mName; + + /** + * @see Object + */ + public String toString() + { + return "Severity[" + mCode + " (" + mName + ")]"; + } + + /** + * @return the name of this severity level. + */ + public String getName() + { + return mName; + } + + /** + * @see Comparable + */ + public int compareTo(Object aObject) + { + SeverityLevel severity = (SeverityLevel) aObject; + return this.mCode - severity.mCode; + } + + /** + * The equals method. + * + * @param aObj Object to compare to. + * + * @return true means equal, false means + * not equal. + */ + public boolean equals(Object aObj) + { + boolean result = false; + + if ((aObj instanceof SeverityLevel) + && (((SeverityLevel) aObj).mCode == this.mCode)) + { + result = true; + } + + return result; + } + + /** + * The hashCode method. + * + * @return hash code for the object. + */ + public int hashCode() + { + return mCode; + } + + /** + * Creates a new SeverityLevel instance. + * + * @param aCode one of the SEVERITYCODE_XYZ values. + * @param aName one of the SEVERITYNAME_XYZ values. + */ + private SeverityLevel(int aCode, String aName) + { + mCode = aCode; + mName = aName; + } + + /** + * SeverityLevel factory method. + * + * @param aSeverityName severity name, such as "ignore", "info", etc. + * @return the SeverityLevel associated with + * aSeverityName + */ + public static SeverityLevel getInstance(String aSeverityName) + { + // canonicalize argument + final String severityName = aSeverityName.trim().toLowerCase(); + + final SeverityLevel retVal = + (SeverityLevel) NAME_TO_SCOPE.get(severityName); + if (retVal == null) { + throw new IllegalArgumentException(severityName); + } + return retVal; + } + + /** + * Ensures that we don't get multiple instances of one SeverityLevel + * during deserialization. See Section 3.6 of the Java Object + * Serialization Specification for details. + * + * @return the serialization replacement object + */ + private Object readResolve() + { + return getInstance(mName); + } +} diff --git a/src/tests/com/puppycrawl/tools/checkstyle/XMLLoggerTest.java b/src/tests/com/puppycrawl/tools/checkstyle/XMLLoggerTest.java index 226409dcb..f9161b75f 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/XMLLoggerTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/XMLLoggerTest.java @@ -20,13 +20,13 @@ import junit.framework.TestCase; public class XMLLoggerTest extends TestCase { private ByteArrayOutputStream outStream; - + public void setUp() throws Exception { outStream = new ByteArrayOutputStream(); } - + public void testEncode() throws IOException { @@ -43,10 +43,10 @@ public class XMLLoggerTest extends TestCase for (int i = 0; i < encodings.length; i++) { final String encoded = logger.encode(encodings[i][0]); assertEquals("\"" + encodings[i][0] + "\"", encodings[i][1], encoded); - } + } outStream.close(); } - + public void testIsReference() throws IOException { @@ -71,36 +71,36 @@ public class XMLLoggerTest extends TestCase for (int i = 0; i < noReference.length; i++) { assertFalse("no reference: " + noReference[i], logger.isReference(noReference[i])); - } - + } + outStream.close(); - } - + } + public void testCloseStream() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, true); + final XMLLogger logger = new XMLLogger(outStream, true); logger.auditStarted(null); logger.auditFinished(null); final String[] expectedLines = {}; verifyLines(expectedLines); } - + public void testNoCloseStream() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, false); + final XMLLogger logger = new XMLLogger(outStream, false); logger.auditStarted(null); logger.auditFinished(null); outStream.close(); final String[] expectedLines = {}; verifyLines(expectedLines); } - + public void testFileStarted() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, true); + final XMLLogger logger = new XMLLogger(outStream, true); logger.auditStarted(null); final AuditEvent ev = new AuditEvent(this, "Test.java"); logger.fileStarted(ev); @@ -108,11 +108,11 @@ public class XMLLoggerTest extends TestCase final String[] expectedLines = {""}; verifyLines(expectedLines); } - + public void testFileFinished() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, true); + final XMLLogger logger = new XMLLogger(outStream, true); logger.auditStarted(null); final AuditEvent ev = new AuditEvent(this, "Test.java"); logger.fileFinished(ev); @@ -124,7 +124,7 @@ public class XMLLoggerTest extends TestCase public void testAddError() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, true); + final XMLLogger logger = new XMLLogger(outStream, true); logger.auditStarted(null); final LocalizedMessage message = new LocalizedMessage( 1, 1, "messages.properties", "key", null); @@ -132,14 +132,14 @@ public class XMLLoggerTest extends TestCase logger.addError(ev); logger.auditFinished(null); final String[] expectedLines = - {""}; + {""}; verifyLines(expectedLines); } - + public void testAddException() throws IOException { - final XMLLogger logger = new XMLLogger(outStream, true); + final XMLLogger logger = new XMLLogger(outStream, true); logger.auditStarted(null); final LocalizedMessage message = new LocalizedMessage( 1, 1, "messages.properties", null, null); @@ -155,7 +155,7 @@ public class XMLLoggerTest extends TestCase }; verifyLines(expectedLines); } - + private String[] getOutStreamLines() throws IOException { @@ -175,7 +175,7 @@ public class XMLLoggerTest extends TestCase reader.close(); return (String[])lineList.toArray(new String[lineList.size()]); } - + /** * Verify output lines from auditStart to auditEnd. * Take into consideration checkstyle element (first and last lines). @@ -196,12 +196,12 @@ public class XMLLoggerTest extends TestCase } assertEquals("last line.", "", lines[lines.length - 1]); } - + private class TestThrowable extends Exception { public void printStackTrace(PrintWriter s) { s.print("stackTrace"); } - } + } }