-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
69728de
commit 23fa562
Showing
8 changed files
with
785 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
103 changes: 103 additions & 0 deletions
103
src/main/java/se/bjurr/violations/lib/parsers/CodeNarcParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package se.bjurr.violations.lib.parsers; | ||
|
||
import static com.google.common.collect.Lists.newArrayList; | ||
import static com.google.common.collect.Maps.newHashMap; | ||
import static javax.xml.stream.XMLStreamConstants.START_ELEMENT; | ||
import static se.bjurr.violations.lib.model.SEVERITY.ERROR; | ||
import static se.bjurr.violations.lib.model.SEVERITY.INFO; | ||
import static se.bjurr.violations.lib.model.SEVERITY.WARN; | ||
import static se.bjurr.violations.lib.model.Violation.violationBuilder; | ||
import static se.bjurr.violations.lib.parsers.ViolationParserUtils.getAttribute; | ||
import static se.bjurr.violations.lib.parsers.ViolationParserUtils.getIntegerAttribute; | ||
import static se.bjurr.violations.lib.reports.Reporter.CODENARC; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.InputStream; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import javax.xml.stream.XMLInputFactory; | ||
import javax.xml.stream.XMLStreamReader; | ||
|
||
import se.bjurr.violations.lib.model.SEVERITY; | ||
import se.bjurr.violations.lib.model.Violation; | ||
|
||
public class CodeNarcParser implements ViolationsParser { | ||
|
||
private SEVERITY getSeverity(Integer from) { | ||
if (from == 1) { | ||
return ERROR; | ||
} | ||
if (from == 2) { | ||
return WARN; | ||
} | ||
return INFO; | ||
} | ||
|
||
@Override | ||
public List<Violation> parseFile(String string) throws Exception { | ||
List<Violation> violations = newArrayList(); | ||
Map<String, String> rules = newHashMap(); | ||
try (InputStream input = new ByteArrayInputStream(string.getBytes())) { | ||
XMLInputFactory factory = XMLInputFactory.newInstance(); | ||
XMLStreamReader xmlr = factory.createXMLStreamReader(input); | ||
String name = null; | ||
String description = null; | ||
while (xmlr.hasNext()) { | ||
int eventType = xmlr.next(); | ||
if (eventType == START_ELEMENT) { | ||
if (xmlr.getLocalName().equals("Rule")) { | ||
name = getAttribute(xmlr, "name"); | ||
} | ||
if (xmlr.getLocalName().equals("Description")) { | ||
description = xmlr.getElementText().trim(); | ||
rules.put(name, description); | ||
} | ||
} | ||
} | ||
} | ||
|
||
try (InputStream input = new ByteArrayInputStream(string.getBytes())) { | ||
|
||
XMLInputFactory factory = XMLInputFactory.newInstance(); | ||
XMLStreamReader xmlr = factory.createXMLStreamReader(input); | ||
|
||
String path = null; | ||
String name = null; | ||
String ruleName = null; | ||
Integer priority = null; | ||
Integer lineNumber = null; | ||
while (xmlr.hasNext()) { | ||
int eventType = xmlr.next(); | ||
if (eventType == START_ELEMENT) { | ||
if (xmlr.getLocalName().equals("Package")) { | ||
path = getAttribute(xmlr, "path"); | ||
|
||
} | ||
if (xmlr.getLocalName().equals("File")) { | ||
name = getAttribute(xmlr, "name"); | ||
} | ||
if (xmlr.getLocalName().equals("Violation")) { | ||
ruleName = getAttribute(xmlr, "ruleName"); | ||
priority = getIntegerAttribute(xmlr, "priority"); | ||
lineNumber = getIntegerAttribute(xmlr, "lineNumber"); | ||
String message = rules.get(ruleName); | ||
if (message == null) { | ||
message = ruleName; | ||
} | ||
Violation violation = violationBuilder()// | ||
.setReporter(CODENARC)// | ||
.setFile(path + "/" + name)// | ||
.setMessage(message)// | ||
.setRule(ruleName)// | ||
.setSeverity(getSeverity(priority))// | ||
.setStartLine(lineNumber)// | ||
.build(); | ||
violations.add(violation); | ||
} | ||
} | ||
} | ||
} | ||
return violations; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package se.bjurr.violations.lib; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static se.bjurr.violations.lib.TestUtils.getRootFolder; | ||
import static se.bjurr.violations.lib.ViolationsReporterApi.violationsReporterApi; | ||
import static se.bjurr.violations.lib.model.SEVERITY.WARN; | ||
import static se.bjurr.violations.lib.reports.Reporter.CODENARC; | ||
|
||
import java.util.List; | ||
|
||
import org.junit.Test; | ||
|
||
import se.bjurr.violations.lib.model.Violation; | ||
|
||
public class CodeNarcTest { | ||
|
||
@Test | ||
public void testThatViolationsCanBeParsed() { | ||
String rootFolder = getRootFolder(); | ||
|
||
List<Violation> actual = violationsReporterApi() // | ||
.withPattern(".*/codenarc/.*\\.xml$") // | ||
.inFolder(rootFolder) // | ||
.findAll(CODENARC) // | ||
.violations(); | ||
|
||
assertThat(actual)// | ||
.hasSize(12); | ||
|
||
assertThat(actual.get(0).getMessage())// | ||
.isEqualTo("In most cases, exceptions should not be caught and ignored (swallowed)."); | ||
assertThat(actual.get(0).getFile())// | ||
.isEqualTo("foo/bar/Test.groovy"); | ||
assertThat(actual.get(0).getSeverity())// | ||
.isEqualTo(WARN); | ||
assertThat(actual.get(0).getRule().get())// | ||
.isEqualTo("EmptyCatchBlock"); | ||
assertThat(actual.get(0).getStartLine())// | ||
.isEqualTo(192); | ||
assertThat(actual.get(0).getEndLine())// | ||
.isEqualTo(192); | ||
|
||
assertThat(actual.get(2).getMessage())// | ||
.isEqualTo( | ||
"Catching Exception is often too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
<?xml version='1.0'?> | ||
<CodeNarc url='http://www.codenarc.org' version='0.10'> | ||
<Report timestamp='Oct 28, 2010 4:10:38 PM'/> | ||
<Project title=''> | ||
<SourceDirectory></SourceDirectory> | ||
</Project> | ||
<PackageSummary totalFiles='192' filesWithViolations='100' priority1='0' priority2='359' | ||
priority3='163'></PackageSummary> | ||
<Package path='foo/bar' totalFiles='11' filesWithViolations='8' | ||
priority1='0' priority2='17' priority3='10'> | ||
<File name='Test.groovy'> | ||
<Violation ruleName='EmptyCatchBlock' priority='2' lineNumber='192'> | ||
<SourceLine><![CDATA[} catch (Exception e) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='CatchException' priority='2' lineNumber='192'> | ||
<SourceLine><![CDATA[} catch (Exception e) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='CatchException' priority='2' lineNumber='218'> | ||
<SourceLine><![CDATA[} catch (Exception directoryNotFound) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='CatchException' priority='2' lineNumber='431'> | ||
<SourceLine><![CDATA[} catch (Exception e) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='CatchException' priority='2' lineNumber='551'> | ||
<SourceLine><![CDATA[} catch (Exception ioe) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='CatchException' priority='2' lineNumber='829'> | ||
<SourceLine><![CDATA[} catch (Exception e) {]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='ThrowException' priority='2' lineNumber='552'> | ||
<SourceLine><![CDATA[throw new Exception("An error occurred while loading the packages" +]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='UnnecessaryGroovyImport' priority='3' lineNumber='28'> | ||
<SourceLine><![CDATA[import java.io.File;]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='UnnecessaryGroovyImport' priority='3' lineNumber='29'> | ||
<SourceLine><![CDATA[import java.io.FileNotFoundException;]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='UnnecessaryGroovyImport' priority='3' lineNumber='30'> | ||
<SourceLine><![CDATA[import java.net.NoRouteToHostException;]]></SourceLine> | ||
</Violation> | ||
<Violation ruleName='UnnecessaryGroovyImport' priority='3' lineNumber='31'> | ||
<SourceLine><![CDATA[import java.net.URL;]]></SourceLine> | ||
</Violation> | ||
</File> | ||
</Package> | ||
<Rules> | ||
<Rule name='BigDecimalInstantiation'> | ||
<Description> | ||
<![CDATA[Checks for calls to the BigDecimal constructors that take a double parameter, which may result in an unexpected BigDecimal value.]]></Description> | ||
</Rule> | ||
<Rule name='BooleanInstantiation'> | ||
<Description> | ||
<![CDATA[Use Boolean.valueOf() for variable values or Boolean.TRUE and Boolean.FALSE for constant values instead of calling the Boolean() constructor directly or calling Boolean.valueOf(true) or Boolean.valueOf(false).]]></Description> | ||
</Rule> | ||
<Rule name='CatchError'> | ||
<Description> | ||
<![CDATA[Catching Error is dangerous; it can catch exceptions such as ThreadDeath and OutOfMemoryError.]]></Description> | ||
</Rule> | ||
<Rule name='CatchException'> | ||
<Description> | ||
<![CDATA[Catching Exception is often too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.]]></Description> | ||
</Rule> | ||
<Rule name='CatchNullPointerException'> | ||
<Description> | ||
<![CDATA[Catching NullPointerException is never appropriate. It should be avoided in the first place with proper null checking, and it can mask underlying errors.]]></Description> | ||
</Rule> | ||
<Rule name='CatchRuntimeException'> | ||
<Description> | ||
<![CDATA[Catching RuntimeException is often too broad or general. It should usually be restricted to framework or infrastructure code, rather than application code.]]></Description> | ||
</Rule> | ||
<Rule name='CatchThrowable'> | ||
<Description> | ||
<![CDATA[Catching Throwable is dangerous; it can catch exceptions such as ThreadDeath and OutOfMemoryError.]]></Description> | ||
</Rule> | ||
<Rule name='CloneableWithoutClone'> | ||
<Description><![CDATA[A class that implements java.lang.Cloneable should define a clone() method.]]></Description> | ||
</Rule> | ||
<Rule name='ConstantIfExpression'> | ||
<Description> | ||
<![CDATA[Checks for if statements with a constant value for the if expression, such as true, false, null, or a literal constant value.]]></Description> | ||
</Rule> | ||
<Rule name='ConstantTernaryExpression'> | ||
<Description> | ||
<![CDATA[Checks for ternary expressions with a constant value for the boolean expression, such as true, false, null, or a literal constant value.]]></Description> | ||
</Rule> | ||
<Rule name='DuplicateImport'> | ||
<Description><![CDATA[Duplicate import statements are unnecessary.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyCatchBlock'> | ||
<Description><![CDATA[In most cases, exceptions should not be caught and ignored (swallowed).]]></Description> | ||
</Rule> | ||
<Rule name='EmptyElseBlock'> | ||
<Description><![CDATA[Empty else blocks are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyFinallyBlock'> | ||
<Description><![CDATA[Empty finally blocks are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyForStatement'> | ||
<Description><![CDATA[Empty for statements are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyIfStatement'> | ||
<Description><![CDATA[Empty if statements are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptySwitchStatement'> | ||
<Description><![CDATA[Empty switch statements are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptySynchronizedStatement'> | ||
<Description><![CDATA[Empty synchronized statements are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyTryBlock'> | ||
<Description><![CDATA[Empty try blocks are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EmptyWhileStatement'> | ||
<Description><![CDATA[Empty while statements are confusing and serve no purpose.]]></Description> | ||
</Rule> | ||
<Rule name='EqualsAndHashCode'> | ||
<Description> | ||
<![CDATA[If either the equals(Object) or the hashCode() methods are overridden within a class, then both must be overridden.]]></Description> | ||
</Rule> | ||
<Rule name='GrailsPublicControllerMethod'> | ||
<Description> | ||
<![CDATA[Checks for public methods on Grails controller classes. Static methods are ignored.]]></Description> | ||
</Rule> | ||
<Rule name='GrailsServletContextReference'> | ||
<Description> | ||
<![CDATA[Checks for references to the servletContext object from within Grails controller and taglib classes.]]></Description> | ||
</Rule> | ||
<Rule name='GrailsStatelessService'> | ||
<Description> | ||
<![CDATA[Checks for fields on Grails service classes. Grails service classes are singletons, by default, and so they should be reentrant and typically stateless. The ignoreFieldNames property specifies one or more field names that should be ignored. The ignoreFieldTypes property specifies one or more field type names that should be ignored. Both can optionally contain wildcard characters ('*' or '?').]]></Description> | ||
</Rule> | ||
<Rule name='ImportFromSamePackage'> | ||
<Description><![CDATA[An import of a class that is within the same package is unnecessary.]]></Description> | ||
</Rule> | ||
<Rule name='ReturnFromFinallyBlock'> | ||
<Description> | ||
<![CDATA[Returning from a finally block is confusing and can hide the original exception.]]></Description> | ||
</Rule> | ||
<Rule name='StringInstantiation'> | ||
<Description> | ||
<![CDATA[Use a String literal (e.g., "...") instead of calling the corresponding String constructor (new String("..")) directly.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowError'> | ||
<Description><![CDATA[Checks for throwing an instance of java.lang.Error.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowException'> | ||
<Description><![CDATA[Checks for throwing an instance of java.lang.Exception.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowExceptionFromFinallyBlock'> | ||
<Description> | ||
<![CDATA[Throwing an exception from a finally block is confusing and can hide the original exception.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowNullPointerException'> | ||
<Description><![CDATA[Checks for throwing an instance of java.lang.NullPointerException.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowRuntimeException'> | ||
<Description><![CDATA[Checks for throwing an instance of <em>java.lang.RuntimeException</em>.]]></Description> | ||
</Rule> | ||
<Rule name='ThrowThrowable'> | ||
<Description><![CDATA[Checks for throwing an instance of java.lang.Throwable.]]></Description> | ||
</Rule> | ||
<Rule name='UnnecessaryBooleanExpression'> | ||
<Description> | ||
<![CDATA[Checks for unnecessary boolean expressions, including ANDing (&&) or ORing (||) with true, false, null, or a Map/List/String/Number literal. Also checks for negation (!) of true, false, null, or a Map/List/String/Number literal.]]></Description> | ||
</Rule> | ||
<Rule name='UnnecessaryGroovyImport'> | ||
<Description> | ||
<![CDATA[A Groovy file does not need to include an import for classes from java.lang, java.util, java.io, java.net, groovy.lang and groovy.util, as well as the classes java.math.BigDecimal and java.math.BigInteger.]]></Description> | ||
</Rule> | ||
<Rule name='UnnecessaryIfStatement'> | ||
<Description> | ||
<![CDATA[Checks for if statements where the if and else blocks are merely returning true and false constants. These cases can be replaced by a simple return statement.]]></Description> | ||
</Rule> | ||
<Rule name='UnnecessaryTernaryExpression'> | ||
<Description> | ||
<![CDATA[Checks for ternary expressions where the conditional expression always evaluates to a boolean and the true and false expressions are merely returning true and false constants. Also checks for ternary expressions where both expressions are the same constant or variable.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedArray'> | ||
<Description> | ||
<![CDATA[Checks for array allocations that are not assigned or used, unless it is the last statement within a block.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedImport'> | ||
<Description> | ||
<![CDATA[Imports for a class that is never referenced within the source file is unnecessary.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedObject'> | ||
<Description> | ||
<![CDATA[Checks for object allocations that are not assigned or used, unless it is the last statement within a block.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedPrivateField'> | ||
<Description><![CDATA[Checks for private fields that are not referenced within the same class.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedPrivateMethod'> | ||
<Description><![CDATA[Checks for private methods that are not referenced within the same class.]]></Description> | ||
</Rule> | ||
<Rule name='UnusedVariable'> | ||
<Description><![CDATA[Checks for variables that are never referenced.]]></Description> | ||
</Rule> | ||
</Rules> | ||
</CodeNarc> |
Oops, something went wrong.