CodeNarc - Creating a RuleSet

Contents

Preferred Way To Configure a RuleSet

NOTE: The preferred way to configure the rules that CodeNarc will use is to create a custom RuleSet specifying the rule names (i.e., without depending on the RuleSet files provided with CodeNarc. This allows finer control over your custom RuleSet and insulates you from the provided RuleSets that can (and often do) change from release to release.

Just Copy and Tweak One of the Starter RuleSet Files

See the Starter RuleSet - All Rules By Category). It contains all of the rules provided with the current version of CodeNarc, organized by category. Just delete or comment out the rules you don’t want to use.

Alternatively, there is a Starter RuleSet - All Rules. It contains all of the rules provided with the current version of CodeNarc, in alphabetical order. Just delete or comment out the rules you don’t want to use.

The Other RuleSet Options Still Work

You can still create your own custom Groovy RuleSet using the older syntax. You can even mix the new rule-name-only syntax with the older Groovy DSL syntax. It’s all good!

You can also continue to use the predefined RuleSets distributed with CodeNarc or you can create your own XML RuleSet. See the site navigation menu for a list of the RuleSets provided out of the box by CodeNarc.

Creating a Groovy RuleSet File

CodeNarc provides a Groovy DSL (domain-specific language) for defining RuleSets.

The preferred syntax for defining a RuleSet is to specify the list of rules using only the rule names. As mentioned above, this allows finer control over your custom RuleSet and insulates you from the provided RuleSets that can (and often do) change from release to release.

A Sample Groovy RuleSet

Here is an example of a Groovy RuleSet file using the preferred syntax:

    ruleset {
        description 'A custom Groovy RuleSet'
    
        CyclomaticComplexity {
            maxMethodComplexity = 1
        }
    
        ClassName
    
        MethodName
    
        ConfusingTernary(priority:3)
    
        StatelessClass {
            name = 'StatelessDao'
            applyToClassNames = '*Dao'
        }
    }

Things to note:

And here is an example that mixes both the preferred (new) syntax along with the older syntax, to illustrate backward-compatibility:

    ruleset {
        MethodName
    
        ConfusingTernary(priority:3)
    
        StatelessClass {
            name = 'StatelessDao'
            applyToClassNames = '*Dao'
        }
    
        // Old style
        rule(org.codenarc.rule.basic.ThrowExceptionFromFinallyBlockRule) {
            priority = 3
        }
    
        // Old style
        ruleset('rulesets/dry.xml')
    }

A Sample Groovy RuleSet Using the Old Syntax

Here is an example of a Groovy RuleSet file using the older syntax:

    import org.codenarc.rule.basic.ThrowExceptionFromFinallyBlockRule
    
    ruleset {
    
        description 'A sample Groovy RuleSet'
    
        ruleset('rulesets/basic.xml') {
            'CatchThrowable' {
                priority = 1
                enabled = false
            }
            'EqualsAndHashCode' priority:3
            exclude 'Empty*'
        }
    
        rule(ThrowExceptionFromFinallyBlockRule) {
            priority = 3
        }
    
        rule("rules/MyCustomRuleScript.groovy")
    
        ruleset('MyGroovyRuleSet.groovy')
    }

Things to note:

About the “inner” ruleset statements:

About the rule statements:

Creating an XML RuleSet File

The XML schema for a CodeNarc RuleSet file is embodied in the “ruleset-schema.xsd” file which is included within the CodeNarc jar. It contains three sections, all of which are optional, though the sections must be in the order listed:

XML Tag Purpose How many are allowed
<description> Describe the purpose of the RuleSet Zero or one
<ruleset-ref> Include a nested RuleSet, optionally configuring and/or filtering the rules within it. The path to the RuleSet can specify either an XML file or a Groovy RuleSet file. Zero or more
<rule> Include a single rule; specify its fully-qualified classname Zero or more
<rule-script> Include a single rule implemented by a groovy script; specify the path of the script. The path is relative to the classpath by default, but can optionally specify a URL prefix. Zero or more

A Sample XML RuleSet

Here is an example XML RuleSet file:

    <ruleset xmlns="http://codenarc.org/ruleset/1.0"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://codenarc.org/ruleset/1.0 http://codenarc.org/ruleset-schema.xsd"
            xsi:noNamespaceSchemaLocation="http://codenarc.org/ruleset-schema.xsd">
    
        <description>Sample rule set</description>
    
        <ruleset-ref path='rulesets/imports.xml'>
            <rule-config name='DuplicateImport'>
                <property name='priority' value='1'/>
            </rule-config>
        </ruleset-ref>
    
        <ruleset-ref path='rulesets/basic.xml'>
            <exclude name='StringInstantiation'/>
        </ruleset-ref>
    
        <rule class='org.codenarc.rule.generic.IllegalRegexRule'>
            <property name="name" value="AuthorTagNotAllowed"/>
            <property name='regex' value='\@author'/>
        </rule>
    
        <rule-script path='rules/MyStaticFieldRule.groovy'/>
    
    </ruleset>

Things to note:

About the <ruleset-ref> elements:

About the <rule> elements:

About the <rule-script> elements:

Filtering Rules Within a RuleSet

You can use the <include> and <exclude> elements within a <ruleset-ref> to filter a RuleSet and include and/or the exclude individual rules. In the following RuleSet excerpt, the entire “rulesets/basic.xml” RuleSet is included, except for the BooleanInstantiationRule and StringInstantiationRule.

    ruleset('rulesets/basic.xml') {
        exclude 'BooleanInstantiation'
        exclude 'StringInstantiation'
    }

And here is the same example in XML RuleSet format:

    <ruleset-ref path='rulesets/basic.xml'>
        <exclude name='BooleanInstantiation'/>
        <exclude name='StringInstantiation'/>
    </ruleset-ref>

Alternatively, you may wish to explicitly specify the rules that you want included from a RuleSet rather than those that are excluded. In the following RuleSet excerpt, ONLY the ReturnFromFinallyBlockRule and StringInstantiationRule rules are included from the “rulesets/basic.xml” RuleSet.

    ruleset('rulesets/basic.xml') {
        include 'ReturnFromFinallyBlockRule'
        include 'StringInstantiation'
    }

And here is the same example in XML RuleSet format:

    <ruleset-ref path='rulesets/basic.xml'>
        <include name='ReturnFromFinallyBlockRule'/>
        <include name='StringInstantiation'/>
    </ruleset-ref>

Note: In all cases, the rule name is specified, not the class name. (In most cases, the rule name is the class name without the “Rule” suffix.)

Note: If you specify at least one <include>, then ONLY rules matching an <include> will be included.

Note: If you specify an <include> and an <exclude> for a rule, then the <exclude> takes precedence.

Using Wildcards Within *include* and *exclude* Names

You may optionally include wildcard characters (‘’ or ‘?’) in the rule *name for both <include> and an <exclude> elements. The wildcard character ‘’ within the *name matches a sequence of zero or more characters in the rule name, while the wildcard character ‘?’ within the name matches exactly one character in the rule name.

In the following RuleSet excerpt, all rules matching ‘Instantiation’ are included from the “rulesets/basic.xml” *RuleSet. In this case, that will include the StringInstantiationRule and BooleanInstantiationRule rules.

    <ruleset-ref path='rulesets/basic.xml'>
        <include name='*Instantiation'/>
    </ruleset-ref>