CodeNarc includes many predefined rules, but you can also create your own custom rules. See the site navigation menu for a list of rules provided out of the box by CodeNarc. CodeNarc provides abstract superclasses and helper classes for creating new rules.
See this screencast showing how easy it is to create a new rule.
All rules must implement the org.codenarc.rule.Rule interface. This interface specifies that all rules must define a name, a priority (from 1 to 3), and also implement the List applyTo(SourceCode sourceCode) method. The method returns the List of Violation objects that result from applying the rule to a single source file.
The org.codenarc.rule.AbstractRule class is the abstract superclass (or ancestor) for all rules provided with CodeNarc. It provides many standard properties and helper methods for subclasses, as described in Standard Properties for Configuring Rules.
Here is an example rule class that is a subclass of AbstractRule:
import org.codenarc.rule.AbstractRule import org.codenarc.source.SourceCode /** * Sample rule. Checks for static fields. */ class MyStaticFieldRule extends AbstractRule { String name = 'MyStaticField' int priority = 2 void applyTo(SourceCode sourceCode, List violations) { sourceCode.ast.classes.each { clazz -> clazz.fields.each { fieldNode -> if (fieldNode.static) { violations << createViolation(sourceCode, fieldNode) } } } } }
Things to note about MyStaticFieldRule class:
See the CodeNarc source code for other examples (look for rule classes that are direct subclasses of AbstractRule).
Many of the rules included with CodeNarc are implemented using the Visitor pattern, as supported by the Groovy AST (Abstract Syntax Tree). See the ClassCodeVisitorSupport class within the Groovy distribution (Javadocs).
Here is an example rule class that is a subclass of AbstractAstVisitorRule that uses an associated AST Visitor class that is a subclass of AbstractAstVisitor. This is the code for the EmptyTryBlock rule included with CodeNarc.
import org.codenarc.rule.AbstractAstVisitor import org.codenarc.rule.AbstractAstVisitorRule import org.codehaus.groovy.ast.stmt.TryCatchStatement import org.codenarc.util.AstUtil class EmptyTryBlockRule extends AbstractAstVisitorRule { String name = 'EmptyTryBlock' int priority = 2 Class astVisitorClass = EmptyTryBlockAstVisitor } class EmptyTryBlockAstVisitor extends AbstractAstVisitor { void visitTryCatchFinally(TryCatchStatement tryCatchStatement) { if (AstUtil.isEmptyBlock(tryCatchStatement.tryStatement)) { addViolation(tryCatchStatement) } super.visitTryCatchFinally(tryCatchStatement) } }
Things to note about this example:
See the CodeNarc source code and javadocs for more information and further examples.
You can also create a new rule using a Groovy script file (typically a .groovy file). The script must still define a class that implements the org.codenarc.rule.Rule interface.
The main advantage is that the rule does not have to be compiled into a .class file first, so you can avoid the compile/build phase, and its associated hassles. The Groovy script file is parsed (and compiled) at runtime.
Here is an example rule script. Note that this is the same source code as in the sample rule class shown above.
import org.codenarc.rule.AbstractRule import org.codenarc.source.SourceCode /** * Sample rule script. Checks for static fields. */ class MyStaticFieldRule extends AbstractRule { String name = 'MyStaticField' int priority = 2 void applyTo(SourceCode sourceCode, List violations) { sourceCode.ast.classes.each { clazz -> clazz.fields.each { fieldNode -> if (fieldNode.static) { violations << createViolation(sourceCode, fieldNode) } } } } }